package com.tairanchina.joat;

import com.tairanchina.joat.exception.JoatInstallException;
import com.tairanchina.joat.exception.JoatLifecycleException;

import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by 周靖捷 on 2016/10/10.
 */
public abstract class PluginManagerDe implements JoatLifecycle {

    protected ConcurrentHashMap<PluginMeta, Plugin> pluginConcurrentHashMap;

    private volatile boolean enabled = true;

    public void init() throws JoatLifecycleException {
        pluginConcurrentHashMap = new ConcurrentHashMap<PluginMeta, Plugin>();
    }

    public void disable() {
        this.enabled = false;
    }

    public Optional<Plugin> getPlugin(PluginMeta pluginMeta) {
        if (enabled)
            return Optional.ofNullable(pluginConcurrentHashMap.get(pluginMeta));
        else
            return Optional.empty();
    }

    public Optional<Plugin> getPlugin(String pluginId) {
        if (enabled) {
            for (PluginMeta pluginMeta : pluginConcurrentHashMap.keySet()) {
                if (pluginMeta.getPluginId().equals(pluginId)) {
                    return Optional.ofNullable(pluginConcurrentHashMap.get(pluginMeta));
                }
            }
        }
        return Optional.empty();
    }

    public void register(PluginMeta pluginMeta) throws JoatInstallException {
        if (pluginMeta != null)
            pluginConcurrentHashMap.put(pluginMeta, pluginMeta.install(this));
    }

    public void unregister(PluginMeta pluginMeta) throws JoatInstallException {
        if (Optional.ofNullable(pluginMeta).isPresent()) {
            pluginMeta.uninstall(this);
            pluginConcurrentHashMap.remove(pluginMeta);
        }
    }

    public void unregister(String pluginId) throws JoatInstallException {
        for (PluginMeta pluginMeta : pluginConcurrentHashMap.keySet()) {
            if (pluginMeta.getPluginId().equals(pluginId)) {
                unregister(pluginMeta);
                return;
            }
        }
    }

    public void decorate(String decoratePluginId, Plugin decoratePlugin) {
        for (PluginMeta meta : pluginConcurrentHashMap.keySet()) {
            if (meta.getPluginId().equals(decoratePluginId)) {
                pluginConcurrentHashMap.put(meta, decoratePlugin);
            }
        }
    }

    public void unDecorate(String decoratePluginId, DecoratorPlugin decoratePlugin) {
        for (PluginMeta meta : pluginConcurrentHashMap.keySet()) {
            if (meta.getPluginId().equals(decoratePluginId)) {
                pluginConcurrentHashMap.put(meta, decoratePlugin.getPlugin());
            }
        }
    }

    public void enable() {
        this.enabled = true;
    }

    public void stop() throws JoatLifecycleException {

    }

    public void destroy() throws JoatLifecycleException {
        for (Plugin plugin : pluginConcurrentHashMap.values()) {
            plugin.destroy();
        }
        pluginConcurrentHashMap.clear();
    }


    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        PluginManagerDe that = (PluginManagerDe) o;

        if (enabled != that.enabled) return false;
        return pluginConcurrentHashMap.equals(that.pluginConcurrentHashMap);

    }

    @Override
    public int hashCode() {
        int result = pluginConcurrentHashMap.hashCode();
        result = 31 * result + (enabled ? 1 : 0);
        return result;
    }
}
